home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianWhisselFiles.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
18KB
|
649 lines
/* 2/15/1993 ScianWhisselFiles.c
NEXRAD file reader */
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianArrays.h"
#include "ScianIcons.h"
#include "ScianWindows.h"
#include "ScianObjWindows.h"
#include "ScianVisWindows.h"
#include "ScianVisObjects.h"
#include "ScianControls.h"
#include "ScianColors.h"
#include "ScianDialogs.h"
#include "ScianFiles.h"
#include "ScianFileSystem.h"
#include "ScianLists.h"
#include "ScianPictures.h"
#include "ScianErrors.h"
#include "ScianTimers.h"
#include "ScianDatasets.h"
#include "ScianFilters.h"
#include "ScianTextBoxes.h"
#include "ScianTitleBoxes.h"
#include "ScianButtons.h"
#include "ScianSliders.h"
#include "ScianScripts.h"
#include "ScianIDs.h"
#include "ScianVisContours.h"
#include "ScianStyle.h"
#include "ScianSpaces.h"
#include "ScianMethods.h"
#include "ScianObjFunctions.h"
#include "ScianWhisselFiles.h"
#include <time.h>
#ifndef ELEVATIONSKIP
#define ELEVATIONSKIP 1100
#define RADIALSKIP 1101
#define GATESKIP 1102
#define DOREFDATASETS 1103
#define DOVELDATASETS 1104
#endif
#define TORADS (3.1415926535898 / 180.0) /* deg -> rad conversion
factor */
#ifndef RELEASE
#ifdef PROTO
void skip_ray(int c, FILE *f)
#else
void skip_ray(c, f)
int c;
FILE *f;
#endif
{
while(c--)
getc(f);
}
#ifdef PROTO
static ObjPtr ReadNXRFile(ObjPtr reader, char *name)
#else
static ObjPtr ReadNXRFile(reader, name)
ObjPtr reader;
char *name;
#endif
{
struct NXRhead header; /* NEXRAD/SciAn file header */
FILE *infile;
char formname[TEMPSTRSIZE];
char refname[TEMPSTRSIZE];
char velname[TEMPSTRSIZE];
char *tc;
int els = 0; /* Number of elevations */
int i, j, k; /* Index variables */
int ii, ji, ki;
float x, y, z, len, inc; /* Used in grid-positioning calculations */
float sinz, cosz, cosr, sinr;
float *cosa, *sina, *h, *s;
float ae = (4.0 * 6371.0) / 3.0; /* Effective Radius of the Earth */
float ref_value_array[256]; /* Array of byte-to-float values for
compressed dataset format */
float vel_value_array[256];
ObjPtr RefForm = NULL; /* Dataforms for Reflectivity */
ObjPtr VelForm = NULL; /* and Velocity */
ObjPtr form = NULL; /* Temp form pointer */
ObjPtr RefDataSet, VelDataSet; /* Datasets for reflec. and vel. */
long dims[3];
real bounds[6]; /* Used to define parameters of datasets */
long indices[3]; /* and dataforms */
float val; /* Conversion vars */
unsigned char uchar;
int elcount, ncount, count;
int sum;
int elskip = 0, radskip = 0, gateskip = 3;
int radmod, gatemod, elmod;
int doref = 1, dovel = 0;
ObjPtr var;
var = GetIntVar("ReadNXRFile", reader, DOREFDATASETS);
if (!var)
doref = 1;
else
doref = GetInt(var);
var = GetIntVar("ReadNXRFile", reader, DOVELDATASETS);
if (!var)
dovel = 1;
else
dovel = GetInt(var);
var = GetRealVar("ReadNXRFile", reader, ELEVATIONSKIP);
if (!var)
elskip = 0;
else
elskip = (int)GetReal(var);
var = GetRealVar("ReadNXRFile", reader, RADIALSKIP);
if (!var)
radskip = 0;
else
radskip = (int)GetReal(var);
var = GetRealVar("ReadNXRFile", reader, GATESKIP);
if (!var)
gateskip = 0;
else
gateskip = (int)GetReal(var);
elmod = elskip + 1;
radmod = radskip + 1;
gatemod = gateskip + 1;
/* Derive a dataset name from the file name */
strcpy(formname, name);
tc = formname;
while (*tc && (*tc != '@') && (*tc != '.'))
tc++;
*tc = '\0';
strcpy(refname, formname);
strcpy(velname, formname);
strcat(formname, ".form");
strcat(refname, ".dBZ");
strcat(velname, ".m/s");
/* Open the file and verify that it contains appropriate data */
if ((infile = fopen(name, "r")) == NULL) {
FileFormatError("ReadNXRFile", "File not accessible");
return NULLOBJ;
}
if (fread(&header, sizeof(header), 1, infile) != 1) {
FileFormatError("ReadNXRFile", "Error reading file header");
fclose(infile);
return NULLOBJ;
}
if (strncmp(header.ident, FVERSION, 6) != 0) {
FileFormatError("ReadNXRFile", "File is not a NEXRAD file");
fclose(infile);
return NULLOBJ;
}
if (strncmp(header.ident, FVERSION, 7) != 0) {
FileFormatError("ReadNXRFile",
"File and reader versions are incompatible");
fclose(infile);
return NULLOBJ;
}
/* Count the number of elevations to be read. */
fprintf(stderr, "Els=%d\n", header.num_els);
if (elskip) {
for (i=0,els=0; i < header.num_els; i++) {
if (!(i % elmod) || (i==header.num_els-1))
els++;
}
} else
els = header.num_els;
/* Establish the grid point dimensions. */
dims[0] = els;
dims[1] = (int)fceil((double)N_RADS / (double)radmod);
dims[2] = (int)fceil((double)N_REFGATES / (double)gatemod);
/*
Build a grid for placing data. Use the reflectivity gate spacing
for both reflectivity and velocity data for the purposes of data
reduction (velocity data is 4x as dense, but covers half the distance).
*/
form = NewDataset(formname, 3, dims, 3);
SetCurField(FIELD1, form);
/* Precalculate the sin/cos of all the radials since these
will be the same for each elevation angle (saves a few
thousand sin/cos calls). */
cosa = (float *)Alloc(N_RADS * sizeof(float));
sina = (float *)Alloc(N_RADS * sizeof(float));
for (j=0; j < N_RADS; j++) {
/* Convert from radial number to sin/cos of the degree
measure of that radial. Radials are numbered clockwise
starting 0.5 degrees east of north. */
cosa[j] = (float) cos((double) (90.0 - (j + 0.5)) * TORADS);
sina[j] = (float) sin((double) (90.0 - (j + 0.5)) * TORADS);
}
h = (float *)Alloc(N_REFGATES * sizeof(float));
s = (float *)Alloc(N_REFGATES * sizeof(float));
inc = (float) header.ref_gatespace / 1000.0;
for (i=0, ii=0; i < header.num_els; i++) { /* elevation loop */
fprintf(stderr,"Doing loop %d\n", i);
/* Are we skipping this elevation? */
if ((i % elmod) && (i<header.num_els-1)) {
continue;
}
indices[0] = ii++;
/* Cache the sin/cos values for this elevation angle. */
sinz = sin((double) (header.elevs[i]*TORADS));
cosz = cos((double) (header.elevs[i]*TORADS));
/* Establish heights and distances for any given ray in
the current elevation scan. */
for (k=0, len=inc/2.0; k < N_REFGATES; k++, len += inc) {
/* Given the distance of the gate (len), h is the height
above the surface of the earth accounting for curvature. */
h[k] = sqrt((double) (len*len + ae*ae + 2.0*len*ae*sinz)) - ae;
/* s is distance along the surface of the earth to the point
underneath the grid point accounting for the curvature. */
s[k] = ae * asin((double)((len*cosz)/(ae + h[k])));
}
if (i == 0) { /* Set x and y bounds from the smallest
elevation angle. */
bounds[0] = -s[N_REFGATES-1];
bounds[1] = s[N_REFGATES-1];
bounds[2] = -s[N_REFGATES-1];
bounds[3] = s[N_REFGATES-1];
bounds[4] = h[0];
} else if (i == header.num_els-1) { /* Set z max from the greatest
elevation angle. */
bounds[5] = h[N_REFGATES-1];
}
for (j=0, ji=0; j < N_RADS; j++) { /* radial loop */
if (!(j % radmod)) {
indices[1] = ji++;
cosr = cosa[j];
sinr = sina[j];
for (k=0, ki=0; k < N_REFGATES; k++) {
if (!(k % gatemod)) {
z = h[k];
x = s[k] * cosr;
y = s[k] * sinr;
indices[2] = ki++;
PutFieldComponent(FIELD1, 0, indices, x);
PutFieldComponent(FIELD1, 1, indices, y);
PutFieldComponent(FIELD1, 2, indices, z);
}
}
}
}
}
Free(sina);
Free(cosa);
Free(h);
Free(s);
/* Now that the grid has been created, turn it into a dataform. */
RefForm = NewCurvilinearDataForm(formname, 3, dims, bounds, form);
/* Now setup the complete datasets. */
if (doref) {
for (i=2; i < 256; i++) {
ref_value_array[i] = (float)(i - 2) / 2.0 - 32.0;
}
ref_value_array[0] = ref_value_array[1] = missingData;
RefDataSet = NewCompressedDataset(refname, 3, dims, 0, ref_value_array);
SetDatasetForm(RefDataSet, RefForm);
}
if (dovel) {
if (header.vel_res == 2) {
for (i=2; i < 256; i++) {
vel_value_array[i] = (float)(i - 2) / 2.0 - 63.5;
}
} else {
for (i=2; i < 256; i++) {
vel_value_array[i] = (float)(i - 129);
}
}
vel_value_array[0] = vel_value_array[1] = missingData;
VelDataSet = NewCompressedDataset(velname, 3, dims, 0, vel_value_array);
SetDatasetForm(VelDataSet, RefForm);
}
/* Read and convert data: for each elevation, reflectivity is first,
then velocity data. */
for (i=0, ii=0; i < header.num_els; i++) {
if ((i % elmod) && (i < header.num_els-1)) {
skip_ray(N_RADS * (N_REFGATES + N_VELGATES), infile);
continue;
}
indices[0] = ii++;
if (doref) { /* Creating Reflectivity datasets? */
fprintf(stderr, "Doing ref elev %d\n", i);
SetCurField(FIELD1, RefDataSet);
for (j=0, ji=0; j < N_RADS; j++) {
if (j % radmod)
skip_ray(N_REFGATES, infile);
else {
indices[1] = ji++;
if (feof(infile))
goto READERROR;
for (k=0, ki=0; k < N_REFGATES; k++) {
uchar = (unsigned char) getc(infile);
if (!(k % gatemod)) {
indices[2] = ki++;
/* val = (uchar <= 1) ? missingData : (uchar - 2) / 2.0 - 32.0; */
PutCompressedFieldComponent(FIELD1, 0, indices, uchar);
}
}
}
}
} else {
skip_ray(N_RADS * N_REFGATES, infile);
}
if (dovel) { /* Creating Velocity datasets? */
/* Read velocity scan using one of two resolution values */
fprintf(stderr, "Doing vel elev %d\n", i);
SetCurField(FIELD1, VelDataSet);
for (j=0, ji=0; j < N_RADS; j++) {
if (j % radmod) {
skip_ray(N_VELGATES, infile);
} else {
elcount = 0;
sum = 0;
ncount = 0;
indices[1] = ji++;
if (feof(infile))
goto READERROR;
for (k=0, ki=0; k < N_VELGATES; k++) {
elcount += header.vel_gatespace;
uchar = (unsigned char) getc(infile);
if (uchar > 1) {
sum += uchar;
ncount++;
}
if (elcount >= header.ref_gatespace * gatemod) {
elcount %= header.ref_gatespace * gatemod;
indices[2] = ki++;
if (ncount)
uchar = (unsigned char)((float)sum / (float)ncount + 0.5);
else
uchar = 0;
PutCompressedFieldComponent(FIELD1, 0, indices, uchar);
sum = 0;
ncount = 0;
}
}
for (; ki < dims[2]; ki++) {
indices[2] = ki;
PutCompressedFieldComponent(FIELD1, 0, indices, (unsigned char)0);
}
}
}
} else {
/* Skip velocity scan */
skip_ray(N_RADS * N_VELGATES, infile);
} /* end if (do velocity dataset) */
} /* end elevation loop */
fclose(infile);
/* The UNIX concept of time (i.e., seconds since 1/1/70 UTC) is
used to express the time of the radar picture. SciAn wants
seconds since midnight, so convert appropriately. */
{
struct tm the_time;
time_t clocktime, result_time;
extern long _timezone, _altzone, _daylight;
clocktime = (time_t) header.file_time;
memcpy((void *)&the_time, (void *)gmtime(&clocktime),
sizeof(struct tm));
/* Reset to midnight of the current day... */
the_time.tm_sec = 0;
the_time.tm_min = 0;
the_time.tm_hour = 0;
/*
Obtain the clock time at midnight. The SG documentation says
mktime() converts from the local timezone domain, so subtract
the difference in seconds between the local time zone and GMT
so that the result will be GMT.
*/
result_time = mktime(&the_time);
if (_daylight)
result_time -= _altzone;
else
result_time -= _timezone;
val = (float)(clocktime - result_time);
}
val += 3600.0;
if (doref)
RegisterTimeDataset(RefDataSet, val);
if (dovel)
RegisterTimeDataset(VelDataSet, val);
return NULLOBJ;
READERROR:
FileFormatError("ReadNXRFile", "Premature EOF!");
fclose(infile);
return NULLOBJ;
}
#endif
#ifdef PROTO
void KillWhisselFiles(void)
#else
void KillWhisselFiles()
#endif
{
}
#ifndef RELEASE
#define NXR_ITEMWIDTH 225
#define NXR_MIDDLE_SEP 45
#define NXR_SMALLER_ITEM 180
#ifdef PROTO
static ObjPtr AddNXRControls(ObjPtr FileReader, ObjPtr PanelContents)
#else
static ObjPtr AddNXRControls(FileReader, PanelContents)
ObjPtr FileReader, PanelContents;
#endif
{
ObjPtr checkbox, textbox, var;
int left, right, bottom, top;
bottom = left = MAJORBORDER;
top = bottom + CHECKBOXHEIGHT;
right = left + NXR_ITEMWIDTH;
/* If DOREFDATASETS has not been created yet, create it and set
it to TRUE. */
var = GetIntVar("AddNXRControls", FileReader, DOREFDATASETS);
if (!var)
SetVar(FileReader, DOREFDATASETS, ObjTrue);
checkbox = NewCheckBox(left, right, bottom, top,
"Create Reflectivity Datasets",
GetPredicate(FileReader, DOREFDATASETS));
PrefixList(PanelContents, checkbox);
SetVar(checkbox, PARENT, PanelContents);
SetVar(checkbox, HELPSTRING, NewString("This option determines whether or \
not reflectivity datasets are generated."));
AssocDirectControlWithVar(checkbox, FileReader, DOREFDATASETS);
left = right + NXR_MIDDLE_SEP;
right = left + NXR_ITEMWIDTH;
/* If DOVELDATASETS has not been created yet, create it and set
it to TRUE. */
var = GetIntVar("AddNXRControls", FileReader, DOVELDATASETS);
if (!var)
SetVar(FileReader, DOREFDATASETS, ObjTrue);
checkbox = NewCheckBox(left, right, bottom, top,
"Create Velocity Datasets",
GetPredicate(FileReader, DOVELDATASETS));
PrefixList(PanelContents, checkbox);
SetVar(checkbox, PARENT, PanelContents);
SetVar(checkbox, HELPSTRING, NewString("This option determines whether or \
not Doppler velocity datasets are generated."));
AssocDirectControlWithVar(checkbox, FileReader, DOVELDATASETS);
left = MAJORBORDER;
right = left + NXR_SMALLER_ITEM;
bottom = top + MINORBORDER;
top = bottom + EDITBOXHEIGHT;
/* Elevation Skip Factors */
textbox = NewTextBox(left, right, bottom, top,
0, "Elevation Skip Text", "Elevation Skip Factor:");
SetVar(textbox, PARENT, PanelContents);
PrefixList(PanelContents, textbox);
left = right + NXR_MIDDLE_SEP;
right = left + NXR_ITEMWIDTH;
var = GetRealVar("AddNXRControls", FileReader, ELEVATIONSKIP);
if (!var)
SetVar(FileReader, ELEVATIONSKIP, NewReal(0.0));
textbox = NewTextBox(left, right, bottom, top,
EDITABLE + WITH_PIT + ONE_LINE,
"Elevation Skip", "0");
SetVar(textbox, PARENT, PanelContents);
PrefixList(PanelContents, textbox);
SetTextAlign(textbox, RIGHTALIGN);
AssocTextRealControlWithVar(textbox, FileReader, ELEVATIONSKIP,
0, plusInf, TR_NE_TOP);
SetVar(textbox, HELPSTRING,
NewString("This value indicates the number of elevation \
scans to skip. The bottom and top elevation angles are always used, \
regardless of this value."));
left = MAJORBORDER;
right = left + NXR_SMALLER_ITEM;
bottom = top + MINORBORDER;
top = bottom + EDITBOXHEIGHT;
/* Radial Skip Factors */
textbox = NewTextBox(left, right, bottom, top,
0, "Radial Skip Text", "Radial Skip Factor:");
SetVar(textbox, PARENT, PanelContents);
PrefixList(PanelContents, textbox);
left = right + NXR_MIDDLE_SEP;
right = left + NXR_ITEMWIDTH;
var = GetRealVar("AddNXRControls", FileReader, RADIALSKIP);
if (!var)
SetVar(FileReader, RADIALSKIP, NewReal(0.0));
textbox = NewTextBox(left, right, bottom, top,
EDITABLE + WITH_PIT + ONE_LINE,
"Radial Skip", "0");
SetVar(textbox, PARENT, PanelContents);
PrefixList(PanelContents, textbox);
SetTextAlign(textbox, RIGHTALIGN);
AssocTextRealControlWithVar(textbox, FileReader, RADIALSKIP,
0, plusInf, TR_NE_TOP);
SetVar(textbox, HELPSTRING,
NewString("This value indicates the number of radials (beams) \
skipped."));
left = MAJORBORDER;
right = left + NXR_SMALLER_ITEM;
bottom = top + MINORBORDER;
top = bottom + EDITBOXHEIGHT;
/* Gate Skip Factors */
textbox = NewTextBox(left, right, bottom, top,
0, "Gate Skip Text", "Gate Skip Factor:");
SetVar(textbox, PARENT, PanelContents);
PrefixList(PanelContents, textbox);
left = right + NXR_MIDDLE_SEP;
right = left + NXR_ITEMWIDTH;
var = GetRealVar("AddNXRControls", FileReader, GATESKIP);
if (!var)
SetVar(FileReader, GATESKIP, NewReal(0.0));
textbox = NewTextBox(left, right, bottom, top,
EDITABLE + WITH_PIT + ONE_LINE,
"Gate Skip", "0");
SetVar(textbox, PARENT, PanelContents);
PrefixList(PanelContents, textbox);
SetTextAlign(textbox, RIGHTALIGN);
AssocTextRealControlWithVar(textbox, FileReader, GATESKIP,
0, plusInf, TR_NE_TOP);
SetVar(textbox, HELPSTRING,
NewString("This value indicates the number of gates \
to skip during file reading."));
return NULLOBJ;
}
#endif
#ifdef PROTO
void InitWhisselFiles(void)
#else
void InitWhisselFiles()
#endif
{
#ifndef RELEASE
ObjPtr fileReader;
fileReader = NewFileReader("NXR");
SetVar(fileReader, EXTENSION, NewString("nxr"));
SetVar(fileReader, HELPSTRING,
NewString("This file reader ingests NEXRAD (NEXt generation RADar) \
volume scans which have been pre-processed by a tape-to-disk file \
converter. Since NEXRAD volume scans can be quite large, file reader \
options have been provided to reduce the amount of data processed."));
SetMethod(fileReader, READALL, ReadNXRFile);
SetMethod(fileReader, ADDCONTROLS, AddNXRControls);
SetVar(fileReader, DOREFDATASETS, ObjTrue);
SetVar(fileReader, DOVELDATASETS, ObjTrue);
SetVar(fileReader, ELEVATIONSKIP, NewReal(0.0));
SetVar(fileReader, RADIALSKIP, NewReal(0.0));
SetVar(fileReader, GATESKIP, NewReal(0.0));
/*EMP added save setting stuff*/
AddSnapVar(fileReader, DOREFDATASETS);
AddSnapVar(fileReader, DOVELDATASETS);
AddSnapVar(fileReader, ELEVATIONSKIP);
AddSnapVar(fileReader, RADIALSKIP);
AddSnapVar(fileReader, GATESKIP);
ApplySavedSettings(fileReader);
#endif
}